package com.iwithlong.service.impl;

import com.imesne.assistant.common.bean.BeanKit;
import com.imesne.assistant.common.exception.ImesneException;
import com.imesne.assistant.common.page.PageList;
import com.imesne.assistant.common.utils.NameUtils;
import com.imesne.assistant.common.validation.Verifier;
import com.imesne.assistant.jdbc.command.entity.Delete;
import com.imesne.assistant.jdbc.command.entity.Select;
import com.imesne.assistant.jdbc.command.entity.Update;
import com.imesne.assistant.jdbc.persist.JdbcDao;
import com.iwithlong.entity.Activity;
import com.iwithlong.entity.Advert;
import com.iwithlong.service.AdvertService;
import com.iwithlong.vo.ActivityVo;
import com.iwithlong.vo.AdvertVo;
import com.ktanx.platform.utils.HttpUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import com.iwithlong.vo.AdvertVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;

@Service
@Transactional
public class AdvertServiceImpl implements AdvertService {

    /**
     * 广告图片文件夹
     */
    private static final String ADVERT_DIR = "advert/";

    @Value("${uploadFilePath:null}")
    private String uploadFilePath;

    @Autowired
    private JdbcDao jdbcDao;

    @Override
    public PageList<AdvertVo> queryPageList(Advert advert) {

        Verifier.init().notBlank(advert.getAdvertType(), "类型").validate();
        Select<Advert> select = jdbcDao.createSelect(Advert.class)
                .where().conditionEntity(advert);
        if (StringUtils.isNotBlank(advert.getTitle())) {
            select.and("title", "like", new Object[]{"%" + advert.getTitle() + "%"});
        }
        select.orderBy("orderNo").asc();

        PageList<Advert> pageList = select.pageList(advert);
        List<AdvertVo> list = BeanKit.convert(AdvertVo.class, pageList);
        for (AdvertVo ad : list) {
            if (StringUtils.equals(ad.getBizType(), Advert.BizType.ACTIVITY.getCode())) {
                Activity activity = jdbcDao.get(Activity.class, ad.getBizId());
                ActivityVo activityVo = BeanKit.convert(new ActivityVo(), activity);
                ad.setActivity(activityVo);
                ad.setFmtGmtCreate(DateFormatUtils.format(activityVo.getBeginDate(), "yyyy.MM.dd"));
            }
        }
        PageList<AdvertVo> resultList = new PageList<>(list);
        resultList.setPager(pageList.getPager());
        return resultList;
    }

    @Override
    public Long add(Advert advert, MultipartFile file) {

        Verifier.init()
                .notNull(advert.getBizId(), "业务id")
                .notBlank(advert.getBizType(), "业务类型")
                .notBlank(advert.getTitle(), "标题")
                .validate();

        if (file == null || file.getSize() == 0) {
            throw new ImesneException("图片不能为空");
        }

        String uniqueFileName = NameUtils.createUniqueFileName(file.getOriginalFilename());
        uniqueFileName = ADVERT_DIR + uniqueFileName;

        try {
//            file.transferTo(new File(uploadFilePath, uniqueFileName));
            FileUtils.copyInputStreamToFile(file.getInputStream(),new File(uploadFilePath, uniqueFileName));
        } catch (IOException e) {
            throw new ImesneException("保存图片文件失败", e);
        }

        advert.setImage(uniqueFileName);
        advert.setGmtCreate(new Date());
        advert.setStatus(Advert.Status.NORMAL.getCode());
        Select<Advert> advertSelect = jdbcDao.createSelect(Advert.class).where("1", 1);
        int count = advertSelect.list().size();
        advert.setOrderNo(count + 1);

        return (Long) jdbcDao.insert(advert);
    }

    @Override
    public PageList<AdvertVo> activityPageList(AdvertVo advertVo) {
        Select<Advert> advertSelect = jdbcDao.createSelect(Advert.class).where("1", 1);
        advertSelect.and("advertType", advertVo.getAdvertType());
        advertSelect.orderBy("orderNo").asc();
        PageList<Advert> adverts = advertSelect.pageList(advertVo);
        List<AdvertVo> advertVos = BeanKit.convert(AdvertVo.class, adverts);
        PageList<AdvertVo> result = new PageList<>(advertVos,adverts.getPager());
        return result;
    }

    @Override
    public void changeStatus(Long[] advertIds,String status) {
        Date date = new Date();
        for (Long advertId : advertIds) {
            Update<Advert> advertUpdate = jdbcDao.createUpdate(Advert.class).where("1",1);
            advertUpdate.and("advertId", advertId);
            advertUpdate.set("status", status);
            if(StringUtils.equals(status,Advert.Status.RELEASE.getCode())){
                advertUpdate.set("gmtIssue",date);
                advertUpdate.set("issuer", HttpUtils.getLoginUser().getRealName());
            }
            advertUpdate.execute();
        }
    }

    @Override
    public void delete(Long[] advertIds) {
        for (Long advertId : advertIds) {
            Delete<Advert> advertDelete = jdbcDao.createDelete(Advert.class).where("1",1);
            advertDelete.and("advertId", advertId);
            advertDelete.execute();
        }
    }

    @Override
    public void update(AdvertVo advertVo,MultipartFile file) {
        Verifier.init()
                .notNull(advertVo.getAdvertId(), "id")
                .notNull(advertVo.getBizId(), "业务id")
                .notBlank(advertVo.getBizType(), "业务类型")
                .notBlank(advertVo.getTitle(), "标题")
                .validate();

        if (file == null || file.getSize() == 0) {
            throw new ImesneException("图片不能为空");
        }

        String uniqueFileName = NameUtils.createUniqueFileName(file.getOriginalFilename());
        uniqueFileName = ADVERT_DIR + uniqueFileName;

        try {
//            file.transferTo(new File(uploadFilePath, uniqueFileName));
            FileUtils.copyInputStreamToFile(file.getInputStream(),new File(uploadFilePath, uniqueFileName));
        } catch (IOException e) {
            throw new ImesneException("保存图片文件失败", e);
        }
        Update<Advert> advertUpdate = jdbcDao.createUpdate(Advert.class).where("1",1);
        advertUpdate.and("advertId",advertVo.getAdvertId());
        advertUpdate.set("title", advertVo.getTitle());
        advertUpdate.set("bizId",advertVo.getBizId());
        advertUpdate.set("bizType", advertVo.getBizType());
        advertUpdate.set("image", uniqueFileName);
        advertUpdate.set("status",Advert.Status.NORMAL.getCode());
        advertUpdate.set("description",advertVo.getDescription());
        advertUpdate.execute();
    }

    @Override
    public AdvertVo findById(Long advertId) {
        Select<Advert> advertSelect = jdbcDao.createSelect(Advert.class).where("1", 1);
        advertSelect.and("advertId", advertId);
        Advert advert = advertSelect.singleResult();
        AdvertVo advertVo = BeanKit.convert(new AdvertVo(), advertSelect.singleResult());
        if(StringUtils.equals(advert.getBizType(),Advert.BizType.ACTIVITY.getCode())){
            Select<Activity> activitySelect = jdbcDao.createSelect(Activity.class).where("1",1);
            activitySelect.and("activityId",advert.getBizId());
            Activity activity = activitySelect.singleResult();
            advertVo.setBizName(activity.getName());
        }
        return advertVo;
    }

    @Override
    public void up(Long advertId) {
        Advert advert = findPoById(advertId);
        int orderNo = advert.getOrderNo();
        List<Advert> recentUpAdverts = getRecentUpAdvert(orderNo, advert.getAdvertType());
        if(CollectionUtils.isEmpty(recentUpAdverts)){
            throw new ImesneException("已经是最顶部");
        }
        Advert recentUpAdvert = recentUpAdverts.get(recentUpAdverts.size()-1);
        int newOrderNo = recentUpAdvert.getOrderNo();
        recentUpAdvert.setOrderNo(advert.getOrderNo());
        advert.setOrderNo(newOrderNo);
        jdbcDao.update(advert);
        jdbcDao.update(recentUpAdvert);
    }

    @Override
    public void down(Long advertId) {
        Advert advert = findPoById(advertId);
        int orderNo = advert.getOrderNo();
        List<Advert> recentDownAdverts = getRecentDownAdvert(orderNo, advert.getAdvertType());
        if(CollectionUtils.isEmpty(recentDownAdverts)){
            throw new ImesneException("已经是最底部");
        }
        Advert recentDownAdvert = recentDownAdverts.get(recentDownAdverts.size() - 1);
        int newOrderNo = recentDownAdvert.getOrderNo();
        recentDownAdvert.setOrderNo(advert.getOrderNo());
        advert.setOrderNo(newOrderNo);
        jdbcDao.update(advert);
        jdbcDao.update(recentDownAdvert);
    }

    @Override
    public void top(Long advertId) {
        Advert advert = findPoById(advertId);
        int orderNo = advert.getOrderNo();
        List<Advert> aboveAdverts = getRecentUpAdvert(orderNo, advert.getAdvertType());
        if(aboveAdverts.size()==0){
            throw new ImesneException("已经是最顶部");
        }
        int newOrderNo = aboveAdverts.get(0).getOrderNo();
        for(int i=0;i<aboveAdverts.size()-1;i++){
            aboveAdverts.get(i).setOrderNo(aboveAdverts.get(i+1).getOrderNo());
        }
        aboveAdverts.get(aboveAdverts.size()-1).setOrderNo(advert.getOrderNo());
        advert.setOrderNo(newOrderNo);
        jdbcDao.update(advert);
        for (Advert aboveAdvert : aboveAdverts) {
            jdbcDao.update(aboveAdvert);
        }
    }

    @Override
    public void bottom(Long advertId) {
        Advert advert = findPoById(advertId);
        int orderNo = advert.getOrderNo();
        List<Advert> lowerAdverts = getRecentDownAdvert(orderNo,advert.getAdvertType());
        if(lowerAdverts.size()==0){
            throw new ImesneException("已经是最底部");
        }
        int newOrderNo = lowerAdverts.get(0).getOrderNo();
        for(int i=0;i<lowerAdverts.size()-1;i++){
            lowerAdverts.get(i).setOrderNo(lowerAdverts.get(i+1).getOrderNo());
        }
        lowerAdverts.get(lowerAdverts.size()-1).setOrderNo(advert.getOrderNo());
        advert.setOrderNo(newOrderNo);
        jdbcDao.update(advert);
        for (Advert aboveAdvert : lowerAdverts) {
            jdbcDao.update(aboveAdvert);
        }
    }

    private List<Advert> getRecentUpAdvert(int orderNo,String type){
        Select<Advert> advertSelect = jdbcDao.createSelect(Advert.class).where("1", 1);
        advertSelect.and("orderNo", "<", new Object[]{orderNo});
        advertSelect.and("advertType",type);
        advertSelect.orderBy("orderNo").asc();
        return advertSelect.list();
    }

    private List<Advert> getRecentDownAdvert(int orderNo,String type){
        Select<Advert> advertSelect = jdbcDao.createSelect(Advert.class).where("1", 1);
        advertSelect.and("orderNo",">",new Object[]{orderNo});
        advertSelect.and("advertType",type);
        advertSelect.orderBy("orderNo").desc();
        return advertSelect.list();
    }

    private Advert findPoById(Long advertId){
        Select<Advert> advertSelect = jdbcDao.createSelect(Advert.class).where("1",1);
        advertSelect.and("advertId", advertId);
        return advertSelect.singleResult();
    }
}
